﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Reflection;
using A2DFramework.XmlService;
using System.Web;
using A2DFramework.AssemblyService;
using ProtoBuf;

namespace A2DFramework.QueueService
{
    [Serializable]
    [ProtoContract]
    public class InnerMessageWrapper
    {
        public InnerMessageWrapper()
        {
            PersistenceType = InnerMessageLocation.InQueue;
        }

        /// <summary>
        /// 消息ID
        /// </summary>
        [ProtoMember(1)]
        public string MessageID { get; set; }

        /// <summary>
        /// 此消息关联的源消息ID
        /// </summary>
        [ProtoMember(2)]
        public string CorrelationID { get; set; }

        [ProtoMember(3)]
        public string RealObjectType { get; set; }

        [ProtoMember(4)]
        public string RealObjectModule { get; set; }

        [ProtoMember(5)]
        public string RealObjectXml { get; set; }

        [ProtoMember(6)]
        public string NetworkLocation { get; set; }

        [ProtoMember(7)]
        public InnerMessageLocation PersistenceType { get; set; }

        public void Inject<T>(T obj)
        {
            this.RealObjectType = typeof(T).FullName;
            this.RealObjectModule = typeof(T).Module.Name;
            string xml = SerializeUtils.Serialize2XML(typeof(T), obj);
            SaveXML(xml);
        }
        public T Extract<T>()
        {
            Assembly assembly=null;
            if (this.RealObjectModule.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)||this.RealObjectModule.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
                assembly = AppDomain.CurrentDomain.Load(this.RealObjectModule.Substring(0, this.RealObjectModule.Length-4));
                
            
            Type type = assembly.GetType(this.RealObjectType);
            string xml = GetXML();
            return (T)SerializeUtils.DeserializeFromXML(type, xml);
        }

        private string GetXML()
        {
            string xml = "";
            if (this.PersistenceType == InnerMessageLocation.InQueue)
            {
                xml = this.RealObjectXml;
            }
            else if (this.PersistenceType == InnerMessageLocation.InNetwork)
            {
                ShareFileBroker fileBroker = new ShareFileBroker(FileService.FileService.Instance());
                xml = fileBroker.GetContentAndDelete(this.NetworkLocation);
            }
            return xml;
        }
        private void SaveXML(string xml)
        {
            if (QueueConfiguration.QueueConfiguration.QueueType==  QueueType.MSMQ
                &&
                xml.Length > QueueConfiguration.QueueConfiguration.MSMQSettings.MaxQueueBodyLength)
            {
                ShareFileBroker fileBroker = new ShareFileBroker(FileService.FileService.Instance());

                this.NetworkLocation = fileBroker.Save(xml);
                this.PersistenceType = InnerMessageLocation.InNetwork;
            }
            else
            {
                this.RealObjectXml = xml;
                this.PersistenceType = InnerMessageLocation.InQueue;
            }
        }
    }
}
